<?php

namespace app\index\service;

use app\common\model\Consulting;
use app\common\model\ConsultingMessage;
use app\common\service\GatewayClientServer;
use app\index\dao\ConsultingMessageDao;
use app\index\traits\MessagePropertyTrait;
use ShidianUtil\Utils\TimeUtil;

/**
 * 消息发送服务
 * Class MessageSendService
 * @package app\consulting\service
 */
class MessageSendService
{
    use MessagePropertyTrait;

    private ConsultingMessageDao $consultingMessageDao;
    private MessageContentService $messageContentService;

    public function __construct(ConsultingMessageDao $consultingMessageDao, MessageContentService $messageContentService)
    {
        $this->consultingMessageDao = $consultingMessageDao;
        $this->messageContentService = $messageContentService;
    }

    /**
     * 发送用户消息
     * @param Consulting $consulting
     * @param $memberType
     * @param $memberId
     * @param $messageType
     * @param array $content
     * @return ConsultingMessage
     */
    public function sendMemberMessage(Consulting $consulting, $memberType, $memberId, $messageType, array $content, $receiveId = '0'): ConsultingMessage
    {
        $senderType = 'member';

        return $this->sendMessage($consulting, $senderType, $memberId, $memberType, $receiveId, $messageType, $content);
    }

    /**
     * 发系统消息
     * @param Consulting $consulting
     * @param $receiveId
     * @param $messageType
     * @param array $content
     */
    public function sendSystemMessage(Consulting $consulting, $receiveId, $messageType, array $content): ConsultingMessage
    {
        $senderType = 'system';
        $senderId = '0';
        $senderMemberType = '0';

        return $this->sendMessage($consulting, $senderType, $senderId, $senderMemberType, $receiveId, $messageType, $content);
    }

    /**
     * 发机器人消息
     * @param Consulting $consulting
     * @param $messageType
     * @param array $content
     * @param $receiveId
     * @param $senderId
     * @return \app\common\model\ConsultingMessage
     */
    public function sendRobotMessage(Consulting $consulting, $senderId, $receiveId, $messageType, array $content): ConsultingMessage
    {
        $senderId = $senderId ?: $consulting->robotId;
        $senderType = 'robot';
        $senderMemberType = 11;

        return $this->sendMessage($consulting, $senderType, $senderId, $senderMemberType, $receiveId, $messageType, $content);
    }

    /**
     * 重发消息
     * @param $id
     * @return ConsultingMessage|null
     */
    public function retransmission($id)
    {
        // 查询前端显示的消息模型
        $record = $this->consultingMessageDao->findConsultingMessage($id);

        // 所属咨询
        $consulting = Consulting::where('id', $record->consultingId)->find();

        // 获取动态的 消息content
        $this->messageContentService->wrapDynamicMessage($record);

        // 推送消息
        $this->pushMessage($record, $consulting, CHAT_UPDATE);

        return $record;
    }

    /**
     * 移除消息
     * @param $id
     * @return void
     */
    public function deleteMessage($id)
    {

        if (!is_id($id)) {
            return;
        }

        $record = ConsultingMessage::where('id', $id)->find();

        if (is_null($record)) {
            return;
        }

        $record->isDel = 1;
        $record->save();

        // 所属咨询
        $consulting = Consulting::where('id', $record->consultingId)->find();

        // 推送消息
        $this->pushMessage($record, $consulting, CHAT_DELETE);

    }

    /**
     * 发消息
     * @param Consulting $consulting
     * @param $senderType
     * @param $senderId
     * @param $senderMemberType
     * @param $receiveId
     * @param $messageType
     * @param array|\stdClass $content
     */
    private function sendMessage(Consulting $consulting, $senderType, $senderId, $senderMemberType, $receiveId, $messageType, $content)
    {
        // 保存消息
        $message = $this->createMessage($consulting->id, $senderType, $senderId, $senderMemberType, $receiveId, $messageType, $content);

        // 触发消息创建事件
        event('ConsultingMessageCreated', ['message' => $message, 'consulting' => $consulting,]);

        // 查询前端显示的消息模型
        $record = $this->consultingMessageDao->findConsultingMessage($message->id);

        // 获取动态的 消息content
        $this->messageContentService->wrapDynamicMessage($record);

        // 推送消息
        $this->pushMessage($record, $consulting);

        return $message;
    }

    /**
     * 创建消息
     * @param $consultingId
     * @param $senderType
     * @param $senderId
     * @param $senderMemberType
     * @param $receiveId
     * @param $messageType
     * @param array $content
     * @return ConsultingMessage
     */
    private function createMessage($consultingId, $senderType, $senderId, $senderMemberType, $receiveId, $messageType, $content): ConsultingMessage
    {

        $params = [
            'consultingId' => $consultingId,
            'senderType' => $senderType,
            'senderId' => $senderId,
            'senderMemberType' => $senderMemberType,
            'receiveId' => $receiveId,
            'messageType' => $messageType,
            'content' => $content,
            'messageTime' => TimeUtil::millitime()
        ];

        // 保存消息
        return $this->consultingMessageDao->insertActive($params, []);
    }

    /**
     * 推送消息
     * @param ConsultingMessage $message
     * @param Consulting $consulting
     * @param string $action
     * @return void
     */
    private function pushMessage(ConsultingMessage $message, Consulting $consulting, string $action = CHAT): void
    {
        if (is_development()) {
            // 本地测试的时候不推送
            return;
        }

        // 转换格式
        $data = [
            'action' => $action,
            'data' => $message->toArray()
        ];

        $gatewayClient = $this->getGatewayClientServer();

        if (is_id($message->receiveId)) {

            $data['data']['isMy'] = $this->getIsMy($message, $message->receiveId);
            $gatewayClient->sendToUid($message->receiveId, json_encode($data));

        } else {

            if (is_id($consulting->lawyerId)) {
                $data['data']['isMy'] = $this->getIsMy($message, $consulting->lawyerId);
                $gatewayClient->sendToUid($consulting->lawyerId, json_encode($data));
            }

            $data['data']['isMy'] = $this->getIsMy($message, $consulting->memberId);
            $gatewayClient->sendToUid($consulting->memberId, json_encode($data));
        }
    }

    private function getGatewayClientServer(): GatewayClientServer
    {
        return app(GatewayClientServer::class);
    }

}
